"""
>>> list(compress(range(10), (not(x % 3) for x in range(10))))
[0, 3, 6, 9]
>>> list(dropwhile(lambda n: n < 5, range(10)))
[5, 6, 7, 8, 9]
>>> list(takewhile(lambda n: n < 5, range(10)))
[0, 1, 2, 3, 4]
>>> list(map(partial(iadd,100), range(5)))
[100, 101, 102, 103, 104]
>>> list(map(lambda x: countOf(x, 3), ([i] * i for i in range(5))))
[0, 0, 0, 3, 0]
>>> list(map(secondpartial(countOf, 3), ([i] * i for i in range(5))))
[0, 0, 0, 3, 0]
>>> list(map(partial(countOf, ..., 3), ([i] * i for i in range(5))))
[0, 0, 0, 3, 0]
>>> list(map(countOf, ([i] * i for i in range(5)), repeat(3)))
[0, 0, 0, 3, 0]
>>> itemgetter('get')({'get':43}) # [str or int]
43
>>> attrgetter('get')({'get':43}) # doctest: +ELLIPSIS
<built-in method get of dict object at 0x...>
>>> methodcaller('get',*('key','default'))({'key':42})
42
>>> methodcaller('get','key2','default')({'key':42})
'default'
"""
from itertools import (
    chain,
    compress,
    starmap,
    zip_longest,
    takewhile,
    dropwhile,
    repeat,
)
from functools import reduce, partial, partialmethod
from operator import *
from random import randint


def secondpartial(f, *args, **kwargs):  # secondpartial(countOf,3)(iterable)
    def finer(second):
        return f(second, *args, **kwargs)

    return finer


def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(
            *(newfunc.leftmost_args + fargs + newfunc.rightmost_args), **newkeywords
        )

    newfunc.func = func
    args = iter(args)
    newfunc.leftmost_args = tuple(takewhile(lambda v: v != Ellipsis, args))
    newfunc.rightmost_args = tuple(args)
    newfunc.keywords = keywords
    return newfunc


if __name__ == "__main__":
    import doctest

    print("itertools 测试开始")
    (ff, tt) = doctest.testmod()
    print("测试结束:统计-失败{},总计{}".format(ff, tt))
    print("√" * tt if tt > 0 and not ff else "无测试" if not ff else "×" * ff)
